"""
智能体基类定义
为所有专业角色提供基础功能
"""
import os
from typing import Dict, List, Any, Optional, Callable, Union, Sequence
from langchain.memory import ConversationBufferMemory
# 不预先导入特定LLM库，将在_create_llm方法中按需导入
from langchain.prompts import PromptTemplate
from crewai import Agent, Task,LLM

from config.settings import OPENAI_API_KEY, OPENAI_MODEL, AGENT_TEMPERATURE, AGENT_MAX_TOKENS, AGENT_MEMORY_SIZE

class BaseInvestmentAgent:
    """投资智能体基类"""
    
    def __init__(
        self,
        name: str,
        role: str,
        goal: str,
        backstory: str,
        tools: Optional[List[Dict[str, Any]]] = None,
        verbose: bool = False
    ):
        """
        初始化投资智能体
        
        参数:
            name: 智能体名称
            role: 智能体角色
            goal: 智能体目标
            backstory: 智能体背景故事
            tools: 智能体可用工具列表
            verbose: 是否输出详细日志
        """
        self.name = name
        self.role = role
        self.goal = goal
        self.backstory = backstory
        self.tools = tools or []
        self.verbose = verbose
        
        # 创建智能体记忆
        # 创建智能体记忆
        self.memory = ConversationBufferMemory(
            return_messages=True,
            memory_key="chat_history"
        )
        
        # 设置LLM
        self.llm = self._create_llm(verbose)
        
        # 创建CrewAI Agent
        self.agent = self._create_agent()
    
    def _create_llm(self, verbose: bool = False):
        """根据配置创建LLM实例"""
        import logging
        logger = logging.getLogger(__name__)
        from config.settings import OPENAI_API_KEY, OPENAI_MODEL, OPENAI_API_BASE
        
        # 清理配置值中的注释
        def clean_config(value):
            if isinstance(value, str):
                return value.split('#')[0].strip()
            return value
        
        # 清理配置并确保模型名称有效
        openai_model = clean_config(OPENAI_MODEL)
        if not openai_model:
            logger.warning(f"OPENAI_MODEL未配置，请检查 config/settings.py 文件")
            return None  # 返回 None，表示 LLM 创建失败
        
        # 输出当前配置值 (用于调试)
        import logging
        logger = logging.getLogger(__name__)
    
        
        try:
            logger.debug("尝试使用model参数创建ChatOpenAI")
            return LLM(
                model=openai_model,
                temperature=AGENT_TEMPERATURE,
                max_retries=3,
                api_key=OPENAI_API_KEY,
                base_url=OPENAI_API_BASE,
                verbose=verbose,
                stream=True  # 添加stream参数以支持qwq-plus-latest模型
            ) if openai_model else None
        except Exception as e:
            logger.debug(f"使用model参数失败，尝试使用model_name: {e}")
            # 尝试旧版API
            return LLM(
                model=openai_model,  # 统一使用model参数
                temperature=AGENT_TEMPERATURE,
                max_retries=3,
                api_key=OPENAI_API_KEY,
                base_url=OPENAI_API_BASE,
                verbose=verbose,
                stream=True  # 添加stream参数以支持qwq-plus-latest模型
            ) if openai_model else None
    
    def _create_agent(self) -> Agent:
        """创建CrewAI Agent实例"""
        import logging
        import traceback
        from functools import wraps
        from time import sleep
        logger = logging.getLogger(__name__)
        
        def retry_on_failure(max_retries=3, delay=1):
            """API调用重试装饰器"""
            def decorator(func):
                @wraps(func)
                def wrapper(*args, **kwargs):
                    last_exception = None
                    for attempt in range(max_retries):
                        try:
                            return func(*args, **kwargs)
                        except Exception as e:
                            last_exception = e
                            logger.warning(f"尝试 {attempt + 1}/{max_retries} 失败: {str(e)}")
                            if attempt < max_retries - 1:
                                sleep(delay)
                    raise RuntimeError(f"Maximum retries ({max_retries}) exceeded") from last_exception
                return wrapper
            return decorator
        
        @retry_on_failure()
        def create_agent_with_tools():
            """带工具集的Agent创建函数"""
            # 打印Agent详细配置
            logger.debug(f"Agent配置详情: role={self.role}, goal={self.goal}, backstory长度={len(self.backstory)}")
            logger.debug(f"LLM类型: {type(self.llm)}")
            # 获取CrewAI版本用于调试
            try:
                from importlib import metadata
                crewai_version = metadata.version("crewai")
                logger.debug(f"CrewAI版本: {crewai_version}")
            except:
                logger.debug("无法获取CrewAI版本信息")
            # 由于CrewAI工具兼容性问题，我们不使用工具
            # 只记录工具信息，但不传递给Agent
            for tool_dict in self.tools:
                if isinstance(tool_dict, dict) and all(key in tool_dict for key in ["name", "description", "func"]):
                    logger.debug(f"注意: 跳过工具 '{tool_dict['name']}' - CrewAI的工具格式与我们的不兼容")
                else:
                    logger.warning(f"跳过无效工具定义: {tool_dict}")
            
            # 创建不带工具的Agent
            logger.info(f"创建Agent: {self.role}")
            agent = Agent(
                role=self.role,
                goal=self.goal,
                backstory=self.backstory,
                # 不使用tools参数
                verbose=self.verbose,
                llm=self.llm
            )
            
            logger.debug("Agent创建成功")
            return agent
            
        try:
            return create_agent_with_tools()
        except Exception as e:
            logger.error(f"创建Agent失败: {str(e)}")
            logger.error(f"详细错误信息: {traceback.format_exc()}")
            raise
    
    def get_agent(self) -> Agent:
        """获取CrewAI Agent实例"""
        return self.agent
    
    @classmethod
    def create_system_prompt(cls, template: str, **kwargs) -> str:
        """创建系统提示模板"""
        prompt = PromptTemplate(
            template=template,
            input_variables=list(kwargs.keys())
        )
        return prompt.format(**kwargs)